package zhieasy.cn.xpu_helper.core.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import zhieasy.cn.xpu_helper.security.detailservice.WechatDetailsService;
import zhieasy.cn.xpu_helper.security.filter.CheckTokenFilter;
import zhieasy.cn.xpu_helper.security.filter.ValidateWechatCodeFilter;
import zhieasy.cn.xpu_helper.security.handler.*;

/**
 * Spring Security配置类
 *  JSR-205 注解/@Secured 注解/prePostEnable
 *  https://blog.csdn.net/qq_40387355/article/details/106846237?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param
 */
@Configuration   //表示该类是一个配置类
@EnableWebSecurity //启用Spring Security
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private WechatDetailsService wechatDetailsService;
    @Autowired
    private LoginFailureHandler loginFailureHandler;
    @Autowired
    private CustomizeAuthenticationEntryPoint customizeAuthenticationEntryPoint;
    @Autowired
    private CustomerLogoutSuccessHandler customerLogoutSuccessHandler;
    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;
    @Autowired
    private LoginSuccessHandler loginSuccessHandler;
    @Autowired
    WeChatSecurityConfig weChatSecurityConfig;
    @Autowired
    CheckTokenFilter checkTokenFilter;
     /**
     * 配置自定义UserDetailsService
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(wechatDetailsService);
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 明文+随机盐值》加密存储
        return new BCryptPasswordEncoder();
    }
    /**
     * 陪权限资源和自定义认证成功和失败管理器
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        ValidateWechatCodeFilter validateWechatCodeFilter = new ValidateWechatCodeFilter();
        validateWechatCodeFilter.setAuthenticationFailureHandler(loginFailureHandler);


//        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
//            //在UsernamePasswordAuthenticationFilter之前加上验证码过滤器
//            .formLogin()
//            .loginPage("/mobile-login.html")
//
//            .and()
//            .authorizeRequests()
//            .antMatchers("/mobile-login.html").permitAll()
//            .antMatchers("/code/*").permitAll()
//            .anyRequest()
//            .authenticated()
//
//            .and()
//            .csrf().disable()
//            //把SmsCodeAuthenticationSecurityConfig配置加进来
//            .apply(smsCodeAuthenticationSecurityConfig);

        http.addFilterBefore(validateWechatCodeFilter, UsernamePasswordAuthenticationFilter.class)
            .addFilterBefore(checkTokenFilter, UsernamePasswordAuthenticationFilter.class)
            .formLogin()
            .loginProcessingUrl("/common/wechat/login")
            // 自定义的登录验证成功或失败后的去向
            .successHandler(loginSuccessHandler).failureHandler(loginFailureHandler)
            // 禁用csrf防御机制(跨域请求伪造)，这么做在测试和开发会比较方便。
            .and().csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            //只开放这个
            .antMatchers("/common/wechat/login").permitAll()
            .antMatchers("/found/object/callback/**").permitAll()
            .antMatchers("/common/role/getRoleListForUser").permitAll()
            .antMatchers("/webjars/**").permitAll()
            .antMatchers("/favicon.ico").permitAll()
            .antMatchers("/swagger-resources/**").permitAll()
            .antMatchers("/v2/**").permitAll()
            .antMatchers("/swagger-ui.html").permitAll()
            .antMatchers("/common/image/**").permitAll()
            .antMatchers("/druid/**").permitAll()
            .antMatchers("/druid").permitAll()
            .antMatchers("/common/image/download/**").permitAll()
            .antMatchers("/common/ad").permitAll()
            //剩下的所有被权限阻挡
            .anyRequest().authenticated()
            .and()
            .exceptionHandling()
            .authenticationEntryPoint(customizeAuthenticationEntryPoint)
            .accessDeniedHandler(customAccessDeniedHandler)
            .and()
            .apply(weChatSecurityConfig);
    }
}
